<template>
  <!-- 飞机飞行：选择航线并沿航线飞行，带轨迹 -->
  <div class="page-wrap">
    <div class="toolbar">
      <el-select
        v-model="selectedId"
        placeholder="选择航线"
        size="small"
        style="width: 220px; margin-right: 8px"
      >
        <el-option
          v-for="r in routes"
          :key="r.id"
          :label="r.name"
          :value="r.id"
        />
      </el-select>
      <el-button size="small" type="primary" @click="startFlight"
        >开始飞行</el-button
      >
      <el-button size="small" @click="stopFlight">停止</el-button>
      <el-button size="small" type="warning" @click="clearTrail"
        >清除轨迹</el-button
      >
    </div>

    <CesiumViewer
      ref="viewerComp"
      :options="viewerOptions"
      :camera="camera"
      :homeZoomOutFactor="0.3"
    >
      <template #entities></template>
    </CesiumViewer>
  </div>
</template>

<script setup>
import {
  ref,
  computed,
  nextTick,
  onMounted,
  onBeforeUnmount,
  watch,
} from "vue";
import * as Cesium from "cesium";
import CesiumViewer from "@/components/cesium/CesiumViewer.vue";
import { useAirRoutesStore } from "@/stores/airroutes";
import { ElMessage } from "element-plus";

const store = useAirRoutesStore();
const routes = computed(() => store.routes);
const selectedId = ref("");

const viewerComp = ref(null);
const viewer = ref(null);

let aircraft = null; // 飞机实体
let trailEntity = null; // 轨迹实体
let verticalEntities = []; // 垂直虚线实体集合

// Canvas 覆盖层（用于绘制航线点与黄线）
let overlay = null;
let ctx = null;
let postRenderRemove = null;

const viewerOptions = {
  animation: false,
  baseLayerPicker: false,
  geocoder: false,
  timeline: false,
  fullscreenButton: true,
  sceneModePicker: true,
};
const camera = {
  lon: 104.195397,
  lat: 35.86166,
  height: 10000000,
  heading: 0,
  pitch: -45,
  roll: 0,
};

onMounted(() => {
  nextTick(() => {
    if (viewerComp.value && typeof viewerComp.value.getViewer === "function")
      viewer.value = viewerComp.value.getViewer();
    const v = viewer.value;
    if (!v) return;
    createCanvasOverlay(v);
  });
});

onBeforeUnmount(() => {
  stopFlight();
  if (postRenderRemove) postRenderRemove();
  if (overlay && overlay.parentNode) overlay.parentNode.removeChild(overlay);
  removeVerticalLines();
});

// 选择航线后，自动飞到“完整视角”以尽可能展示全航线，并重绘画布
watch(selectedId, (id) => {
  const v = viewer.value;
  if (!v) return;
  const route = routes.value.find((r) => r.id === id);
  redrawCanvas();
  updateVerticalLines();
  if (!route || !route.points || route.points.length === 0) return;
  const pts = route.points.map((p) =>
    Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.height || 0)
  );
  const bs = Cesium.BoundingSphere.fromPoints(pts);
  const pitch = Cesium.Math.toRadians(-30);
  const range = Math.max(bs.radius * 2.0, 5000);
  v.camera.flyToBoundingSphere(bs, {
    duration: 0.8,
    offset: new Cesium.HeadingPitchRange(0, pitch, range),
  });
});

function startFlight() {
  const v = viewer.value;
  if (!v) return;
  const route = routes.value.find((r) => r.id === selectedId.value);
  if (!route) {
    ElMessage.warning("请选择航线");
    return;
  }
  const pts = route.points;
  if (!pts || pts.length < 2) {
    ElMessage.warning("航线点不足");
    return;
  }

  // 1) 设置时间轴
  const start = Cesium.JulianDate.now();
  const stop = Cesium.JulianDate.addSeconds(
    start,
    pts.length * 2,
    new Cesium.JulianDate()
  ); // 每点2秒演示
  v.clock.startTime = start.clone();
  v.clock.stopTime = stop.clone();
  v.clock.currentTime = start.clone();
  v.clock.clockRange = Cesium.ClockRange.CLAMPED;
  v.clock.multiplier = 1;

  // 2) 采样位置
  const property = new Cesium.SampledPositionProperty();
  pts.forEach((p, i) => {
    const time = Cesium.JulianDate.addSeconds(
      start,
      i * 2,
      new Cesium.JulianDate()
    );
    const pos = Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.height || 0);
    property.addSample(time, pos);
  });

  // 3) 飞机实体（用点代替，可换 glTF 模型）
  if (aircraft) {
    v.entities.remove(aircraft);
    aircraft = null;
  }
  aircraft = v.entities.add({
    availability: new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({ start, stop }),
    ]),
    position: property,
    point: { pixelSize: 10, color: Cesium.Color.RED },
    orientation: new Cesium.VelocityOrientationProperty(property),
    path: {
      material: Cesium.Color.YELLOW,
      width: 2,
      leadTime: 0,
      trailTime: 60,
    },
  });

  // 4) 轨迹（固化）
  if (trailEntity) {
    v.entities.remove(trailEntity);
    trailEntity = null;
  }
  const degHeights = pts.flatMap((p) => [p.lon, p.lat, p.height || 0]);
  trailEntity = v.entities.add({
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArrayHeights(degHeights),
      width: 2,
      material: Cesium.Color.ORANGE.withAlpha(0.6),
    },
  });

  // 5) 相机飞到航线范围
  const bs = Cesium.BoundingSphere.fromPoints(
    pts.map((p) => Cesium.Cartesian3.fromDegrees(p.lon, p.lat, p.height || 0))
  );
  v.camera.flyToBoundingSphere(bs, {
    duration: 1.0,
    offset: new Cesium.HeadingPitchRange(
      0,
      Cesium.Math.toRadians(-30),
      bs.radius * 2.0
    ),
  });

  // 5.1) 更新垂直虚线
  updateVerticalLines();

  // 6) 开始
  v.clock.shouldAnimate = true;
}

function stopFlight() {
  const v = viewer.value;
  if (!v) return;
  v.clock.shouldAnimate = false;
}

function clearTrail() {
  const v = viewer.value;
  if (!v) return;
  if (trailEntity) {
    v.entities.remove(trailEntity);
    trailEntity = null;
  }
  removeVerticalLines();
}

// ===== Canvas 覆盖层绘制：蓝色序号点 + 黄色连接线 =====
function createCanvasOverlay(v) {
  overlay = document.createElement("canvas");
  overlay.style.position = "absolute";
  overlay.style.left = 0;
  overlay.style.top = 0;
  overlay.style.pointerEvents = "none";
  overlay.style.zIndex = 999;
  v.container.appendChild(overlay);
  function resize() {
    const w = v.canvas.clientWidth;
    const h = v.canvas.clientHeight;
    overlay.style.width = w + "px";
    overlay.style.height = h + "px";
    overlay.width = Math.max(1, Math.floor(w));
    overlay.height = Math.max(1, Math.floor(h));
    ctx = overlay.getContext("2d");
    redrawCanvas();
  }
  const ro = new ResizeObserver(resize);
  ro.observe(v.container);
  resize();
  const pr = () => redrawCanvas();
  v.scene.postRender.addEventListener(pr);
  postRenderRemove = () => {
    try {
      v.scene.postRender.removeEventListener(pr);
    } catch (_) {}
  };
}

function worldToScreen(v, lon, lat, height) {
  const cart = Cesium.Cartesian3.fromDegrees(lon, lat, height || 0);
  if (typeof v.scene.cartesianToCanvasCoordinates === "function")
    return v.scene.cartesianToCanvasCoordinates(cart);
  if (
    Cesium.SceneTransforms &&
    typeof Cesium.SceneTransforms.wgs84ToWindowCoordinates === "function"
  )
    return Cesium.SceneTransforms.wgs84ToWindowCoordinates(v.scene, cart);
  return null;
}

function redrawCanvas() {
  if (!ctx || !viewer.value) return;
  const v = viewer.value;
  const w = overlay.width,
    h = overlay.height;
  ctx.clearRect(0, 0, w, h);
  const route = routes.value.find((r) => r.id === selectedId.value);
  const pts = route && route.points ? route.points : [];
  if (!pts.length) return;
  // 连接线
  if (pts.length >= 2) {
    ctx.beginPath();
    pts.forEach((p, i) => {
      const win = worldToScreen(v, p.lon, p.lat, p.height || 0);
      if (!win) return;
      if (i === 0) ctx.moveTo(win.x, win.y);
      else ctx.lineTo(win.x, win.y);
    });
    ctx.lineWidth = 4;
    ctx.strokeStyle = "#FFD200";
    ctx.lineJoin = "round";
    ctx.lineCap = "round";
    ctx.stroke();
  }
  // 点位
  pts.forEach((p, i) => {
    const win = worldToScreen(v, p.lon, p.lat, p.height || 0);
    if (!win) return;
    ctx.beginPath();
    ctx.arc(win.x, win.y, 10, 0, Math.PI * 2);
    ctx.fillStyle = "#1677ff";
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = "#ffffff";
    ctx.stroke();
    ctx.fillStyle = "#ffffff";
    ctx.font = "12px sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText(String(i + 1), win.x, win.y);
  });
}

// ===== 垂直虚线：每个点位从地面到该高度 =====
function updateVerticalLines() {
  const v = viewer.value;
  if (!v) return;
  removeVerticalLines();
  const route = routes.value.find((r) => r.id === selectedId.value);
  const pts = route && route.points ? route.points : [];
  pts.forEach((p) => {
    const base = Cesium.Cartesian3.fromDegrees(p.lon, p.lat, 0);
    const h = Number(p.height || 180);
    const top = Cesium.Cartesian3.fromDegrees(p.lon, p.lat, h);
    const e = v.entities.add({
      polyline: {
        positions: [base, top],
        width: 2,
        clampToGround: false,
        material: new Cesium.PolylineDashMaterialProperty({
          color: Cesium.Color.fromCssColorString("#00e5ff"),
          dashLength: 16,
          dashPattern: 255,
        }),
      },
      show: true,
    });
    verticalEntities.push(e);
  });
  try {
    v.requestRender && v.requestRender();
  } catch (_) {}
}

function removeVerticalLines() {
  const v = viewer.value;
  if (!v) return;
  verticalEntities.forEach((e) => {
    try {
      v.entities.remove(e);
    } catch (_) {}
  });
  verticalEntities = [];
}
</script>

<style scoped>
.page-wrap {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
.toolbar {
  position: absolute;
  right: 12px;
  top: 12px;
  z-index: 20;
  background: rgba(255, 255, 255, 0.9);
  padding: 6px 8px;
  border-radius: 6px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
}
</style>
